#include "User.pb.h"
#include "MprpcApplication.h"
#include "MprpcProvider.h"

#include <iostream>
#include <string>

/**
 * 我们利用业务去驱动框架的编写
 * 下面实际是对框架的使用
 */
class UserService : public fixbug::UserServiceRpc
{
public:
    bool Login(std::string name, std::string pwd)
    {
        std::cout << "doing local service: Login" << std::endl;
        std::cout << "name:" << name << " pwd:" << pwd << std::endl;
        return true;
    }

    bool Register(uint32_t id, std::string name, std::string pwd)
    {
        std::cout << "doing local service: Register" << std::endl;
        std::cout << "id:" << id << " name:" << name << " pwd:" << pwd << std::endl;
        return true;
    }

    /**
     * 重写基类UserServiceRpc的虚函数
     * (2) caller ===> Login(LoginRequest) ===> muduo ===> callee
     * (1) callee ===> Login(LoginRequest) ===> 交给下面重写的Login方法，在里边调用本地的Login函数
     */
    void Login(google::protobuf::RpcController *controller,
               const ::fixbug::LoginRequest *request,
               fixbug::LoginResponse *response,
               google::protobuf::Closure *done)
    {
        // 1. 从请求中获取数据。request是框架帮我们反序列化出的
        std::string name = request->name();
        std::string pwd = request->pwd();

        // 2. 执行本地Login函数
        bool login_result = Login(name, pwd);

        // 3. 把响应填入LoginResponse。我们使用框架，只管填写，反序列化由框架完成
        fixbug::ResultCode *result = response->mutable_result(); // 获取result字段的地址
        result->set_errcode(0);
        result->set_errmsg("");
        response->set_success(login_result);

        // 4. 执行回调操作，即响应对象数据response的序列化和网络发送（由框架完成）
        done->Run();
    }

    void Register(google::protobuf::RpcController *controller,
                  const ::fixbug::RegisterRequest *request,
                  fixbug::RegisterResponse *response,
                  google::protobuf::Closure *done)
    {
        uint32_t id = request->id();
        std::string name = request->name();
        std::string pwd = request->pwd();

        bool ret = Register(id, name, pwd);

        fixbug::ResultCode *result = response->mutable_result(); // 获取result字段的地址
        result->set_errcode(0);
        result->set_errmsg("");
        response->set_success(ret);

        done->Run();
    };
};

// ./provider -i config.conf
int main(int argc, char *argv[])
{
    // 调用框架的初始化函数，传入命令行参数
    MprpcApplication::Init(argc, argv);

    // provider是一个rpc网络服务对象。把UserService对象发布到rpc节点上
    MprpcProvider provider;
    provider.NotifyService(new UserService());

    // 启动一个rpc服务节点，  Run以后，进程进入阻塞状态，等待远程的rpc调用请求
    provider.Run();

    return 0;
}
